﻿using JT808.Protocol.MessageBody;
using JT808.Protocol.MessagePack;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Protocol.Formatters.MessageBodyFormatters
{
    public class JT808_0x0900_Formatter : IJT808MessagePackFormatter<JT808_0x0900>
    {
        public JT808_0x0900 Deserialize(ref JT808MessagePackReader reader, IJT808Config config)
        {
            var list = new List<JT808_0x0900_Sub>();
            var main = new JT808_0x0900();
            main.transmission = reader.ReadByte();
            main.equipmentmodel = reader.ReadByte();
            reader.Skip(2);
            main.tyresnumber = Convert.ToInt32(reader.ReadByte());
            for (int i = 0; i < main.tyresnumber.Value; i++)
            {
                var f2 = new JT808_0x0900_Sub();
                f2.tyreposition = Convert.ToInt32((byte)(reader.ReadByte() << 3) >> 3);
                f2.sensorid = reader.ReadHex(3);
                f2.powervalue = Convert.ToDecimal((byte)(reader.ReadByte() >> 4)) + 1.9m;
                reader.Back();
                f2.pressvalue = Convert.ToDecimal((ushort)(reader.ReadUInt16() << 6) >> 6) * 0.025m;
                var t1 = Convert.ToDecimal(reader.ReadByte());
                f2.temperaturevalue = t1 == -50m ? 0 : (t1 - 50.0m);
                f2.ispowerinvalue = (reader.ReadByte() >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.isnogetsender = ((byte)(reader.ReadByte() << 1) >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.isproofrun = ((byte)(reader.ReadByte() << 2) >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.ispresshigh = ((byte)(reader.ReadByte() << 3) >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.ispresslower = ((byte)(reader.ReadByte() << 4) >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.istemperaturehigh = ((byte)(reader.ReadByte() << 5) >> 7) == 0x01 ? true : false;
                reader.Back();
                f2.statusNow = ((byte)(reader.ReadByte() << 6) >> 6);
                list.Add(f2);
            }
            main.list = list;
            main.latitude = Convert.ToInt32(reader.ReadUInt32()) / 1000000.0m;
            main.longitude = Convert.ToInt32(reader.ReadUInt32()) / 1000000.0m;
            main.createtime = reader.ReadDateTime6();
            return main;
        }

        public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0900 value, IJT808Config config)
        {
            writer.WriteByte(value.transmission);
            writer.WriteByte(value.equipmentmodel);
            writer.WriteUInt16(0);
            writer.WriteByte((byte)value.tyresnumber.Value);
            foreach (var t in value.list)
            {
                writer.WriteByte((byte)t.tyreposition.Value);
                writer.WriteHex(t.sensorid, 3);
                ushort high = (ushort) (((byte)(t.powervalue.Value - 1.9m)) << 8);
                ushort low = (ushort)(t.pressvalue.Value / 0.025m);
                writer.WriteUInt16((ushort)(high+low));
                writer.WriteByte((byte)(t.temperaturevalue.Value + 50.0m));
                string sn = "00";
                switch (t.statusNow)
                {
                    case 1: sn = "01"; break;
                    case 2: sn = "10"; break;
                    case 3: sn = "11"; break;
                    default:
                        sn = "00";
                        break;
                }
                string state =  (t.ispowerinvalue.Value ? "1" : "0") + (t.isnogetsender.Value ? "1" : "0") + (t.isproofrun.Value ? "1" : "0") 
                    + (t.ispresshigh.Value ? "1" : "0") + (t.ispresslower.Value ? "1" : "0") + (t.istemperaturehigh.Value ? "1" : "0") + sn;
                writer.WriteByte(Convert.ToByte(state, 2));
            }
            writer.WriteUInt32((uint)(value.latitude.Value * 1000000));
            writer.WriteUInt32((uint)(value.longitude.Value * 1000000));
            writer.WriteDateTime6(value.createtime.Value);
        }
    }
}
